home *** CD-ROM | disk | FTP | other *** search
- ;*************************************************************************
- ;** mmu.library **
- ;** **
- ;** a system library for arbitration and control of the MC68K MMUs **
- ;** **
- ;** © 1998 THOR-Software, Thomas Richter **
- ;** No commercial use, reassembly, modification without prior, written **
- ;** permission of the authors. **
- ;** Including this library in any commercial software REQUIRES a **
- ;** written permission and the payment of a small fee. **
- ;** **
- ;** This is an internal header file, do not depend on anything here. **
- ;** Use the official include files. **
- ;** Distributed only for the mmu.library development group for private **
- ;** use. **
- ;** **
- ;**---------------------------------------------------------------------**
- ;** Block: Context related operations **
- ;** Version 0.04 02.10.1998 **
- ;*************************************************************************
-
- ;FOLD Includes
- include inc:macros.asm
- include inc:exec_lib.asm
- include inc:expansion_lib.asm
- include mu_lib.i
- include mu_context.i
- include mu_alerts.i
- ;ENDFOLD
- ;FOLD External References
- xref AllocContextMem
- xref FreeContextMem
- xref MUAlert
- xref FreeMMUTable
- ;ENDFOLD
- ;FOLD Defines
- MemList = $142
-
- mh_Attributes = $0e
- mh_Lower = $14
- mh_Upper = $18
-
- ERTB_MEMLIST = $05 ;ConfigReg type is memory
- er_Type = $10 ;Offset of the type in the configreg
- cd_BoardAddr = $20
- cd_BoardSize = $24
- ;ENDFOLD
-
- section main_code,code
-
- ;FOLD AllocContext
- ;*************************************************
- ;** AllocContext **
- ;** allocate a context structure -> d0 **
- ;** or NULL on error **
- ;*************************************************
- xdef AllocContext
- AllocContext:
- saveregs a2-a3/a6
- move.l #ctx_len,d0
- bsr AllocContextMem
- beq.s .exit
- move.l d0,a2
-
- lea mulib_cpstart(a6),a0
- lea ctx_cpstart(a2),a1
- for.l #(ctx_cpend-ctx_cpstart)/4,d0
- move.l (a0)+,(a1)+
- next d0
-
- moveq #map_len,d0
- bsr AllocContextMem
- beq.s .exit ;get memory for blank mapping
- move.l d0,a3
- lea ctx_Mapping(a2),a1
- lea ctx_Semaphore(a2),a0
- NewList a1 ;initialize the Mapping list
- move.l mulib_SysBase(a6),a6
- jsr InitSemaphore(a6) ;initialize the semaphore
-
- subq.l #1,map_higher(a3) ;higher address is 0xfff.fff
- bsetm mapp_blank,map_properties(a3) ;blank space, access must be emulated
- bsetm ctxf_dirty,ctx_flags(a2) ;this context lacks a CPU table
- bsetm mapf_dirty,map_flags(a3) ;CPU Table is yet to be build
- lea ctx_Mapping(a2),a0
- move.l a3,a1
- AddHead
-
- move.l a2,d0
- bra.s .exit
- .free: ;on error
- move.l a2,a1
- bsr FreeContextMem
- moveq #0,d0
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD FreeContext
- ;*************************************************
- ;** FreeContext **
- ;** release the context structure in *a0 **
- ;*************************************************
- xdef FreeContext
- FreeContext:
- saveregs a2
- move.l a0,a2
-
- btstm ctxf_active,ctx_Flags(a2) ;is this thing active ?
- beq.s .releaseme
-
- pea AN_FreeActive
- bsr MUAlert
- bra.s .exit
-
- .releaseme:
- do
- lea ctx_Mapping(a2),a0
- RemHead
- tst.l d0
- break.s eq
- move.l d0,a1
- bsr FreeContextMem ;release the mapping nodes
- loop.s
-
- ;now release the complete MMU table
- move.l a2,a0
- bsr FreeMMUTable
-
- move.l a2,a1
- bsr FreeContextMem ;release the context itself
-
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD LockContext
- ;*************************************************
- ;** LockContext **
- ;** Lock the context in *a0 **
- ;** does not alter any registers **
- ;*************************************************
- xdef LockContext
- LockContext:
- saveregs a0/a6
- move.l mulib_SysBase(a6),a6
- lea ctx_Semaphore(a0),a0
- jsr ObtainSemaphore(a6)
- loadregs
- rts
- ;ENDFOLD
- ;FOLD UnlockContext
- ;*************************************************
- ;** UnlockContext **
- ;** Unlock, i.e. release the semaphore *a0 **
- ;** does not alter any registers **
- ;*************************************************
- xdef UnlockContext
- UnlockContext:
- saveregs a0/a6
- move.l mulib_SysBase(a6),a6
- lea ctx_Semaphore(a0),a0
- jsr ReleaseSemaphore(a6)
- loadregs
- rts
- ;ENDFOLD
-
- ;FOLD DefineMapping
- ;*************************************************
- ;** DefineMapping **
- ;** add a new mapping for the context *a0 **
- ;** given in *a1 **
- ;** returns FALSE in case of failure **
- ;** Does NOT force a rebuild of the MMU tables **
- ;** but sets the dirty flags **
- ;** doesn't do any sanity checks **
- ;*************************************************
- xdef DefineMapping
- DefineMapping:
- saveregs a2-a4/d2-d7
-
- move.l a0,a2 ;keep the context
- move.l a1,a3 ;and the new mapping
- bsr LockContext ;need exclusive access
-
- movem.l map_lower(a3),d2-d3 ;lower bounds
- move.l ctx_Mapping(a2),a4 ;get the first mapping node
- do
- tst.l (a4) ;end of the list reached ?
- beq .okdone
- movem.l map_lower(a4),d4-d5 ;get bounds here, too
- move.l d2,d6
- move.l d3,d7
- cmp.l d2,d4
- blo.s .nomax
- move.l d4,d6 ;get maximum of minima
- .nomax:
- cmp.l d3,d5
- bhi.s .nomin
- move.l d5,d7 ;get minimum of maxima
- .nomin:
- ;[d6,d7] is now the intersection
- cmp.l d6,d7
- bls .nextchk ;intersection emtpy?
- ;the intersection is always A PART of the already existing node!
- ;check whether we've to modify anything at all!
- movem.l map_Properties(a3),d0/a0 ;properties and delta
- move.l map_Properties(a4),d1
- cmp.l map_Delta(a4),a0
- bne.s .modify ;if equal, do not modify this
- eor.l d0,d1
- and.l map_Mask(a3),d1
- beq .next
-
- .modify:
- cmp.l d4,d6 ;remove a lower part of this block?
- beq.s .noadjustbottom
- ;here we've to set aside the lower part of the old block
- moveq #map_len,d0
- bsr AllocContextMem ;get memory
- beq .fail ;on failure: exit
- move.l d0,a1 ;keep it
- move.l map_Properties(a4),map_Properties(a1)
- bsetm mapf_dirty,map_flags(a4) ;this is dirty
- move.l d6,d0
- move.l map_UserPtr(a4),map_UserPtr(a1) ;copy properties
- subq.l #1,d0
- move.l map_lower(a4),map_lower(a1) ;lower is this one
- move.l map_flags(a4),map_flags(a1) ;copy the flags, too
- move.l d0,map_higher(a1) ;insert higher
- move.l d6,map_lower(a4) ;modify lower of this thing
- bsetm ctxf_dirty,ctx_Flags(a2) ;context is dirty, too
- move.l a4,a0
- InsertBefore ;insert that in front of me
- reloop ;rerun with the modified node
-
- .noadjustbottom: ;check now the head
- cmp.l d5,d7
- beq.s .noadjusttop
-
- moveq #map_len,d0
- bsr AllocContextMem ;get memory
- beq .fail ;on failure: exit
- move.l d0,a1 ;keep it
- move.l map_Properties(a4),map_Properties(a1)
- bsetm mapf_dirty,map_flags(a4) ;this is dirty
- move.l d7,d0
- move.l map_UserPtr(a4),map_UserPtr(a1) ;copy properties
- addq.l #1,d0
- move.l map_higher(a4),map_higher(a1) ;higher is this one
- move.l map_flags(a4),map_flags(a1) ;copy the flags, too
- move.l d0,map_lower(a1) ;insert new lower
- move.l d7,map_higher(a4) ;modify higher of this thing
- bsetm ctxf_dirty,ctx_Flags(a2) ;context is dirty, too
- move.l a4,a0
- InsertAfter ;insert that in behind me
- reloop ;rerun with the modified node
-
- .noadjusttop: ;here: The thing fits perfectly. Insert the modified properties
- move.l map_Properties(a4),d0 ;A: old properties
- move.l map_Properties(a3),d1 ;B: new properties
- move.l map_UserPtr(a3),map_UserPtr(a4)
- eor.l d0,d1 ;AxB
- bsetm mapf_dirty,map_flags(a4) ;something was modified
- and.l map_Mask(a3),d1 ;and M
- eor.l d0,d1 ;xA
- bsetm ctxf_dirty,ctx_flags(a2) ;ditto in the context
- move.l d1,map_Properties(a4) ;=((AxB)^M)xA)=(A^M)v(A^_M)
- ;now check if the lower neighbor has the same
- ;properties. If so, we can remove it
- move.l 4(a4),a1 ;get lower
- move.l a1,d0
- tst.l 4(a1) ;really available ?
- beq.s .chkupper
-
- lea map_Properties(a4),a0
- lea map_Properties(a1),a1
- cmp.l (a0)+,(a1)+
- bne.s .chkupper
- cmp.l (a0)+,(a1)+
- bne.s .chkupper
- ;here: Identical. Remove lower
- move.l d0,a1 ;restore lower
- move.l map_flags(a1),d1
- move.l d0,d6
- move.l map_lower(a1),map_lower(a4) ;carry over the lower boundary
- or.l d1,map_flags(a4) ;carry over flags
- Remove ;remove this node
- move.l d6,a1
- bsr FreeContextMem ;release it again
- .chkupper:
- move.l (a4),a1 ;get next
- move.l a1,d0
- tst.l (a1) ;is there a next
- beq.s .nextchk ;no, so we're done
-
- lea map_Properties(a4),a0
- lea map_Properties(a1),a1
- cmp.l (a0)+,(a1)+
- bne.s .nextchk
- cmp.l (a0)+,(a1)+
- bne.s .nextchk
-
- move.l d0,a1 ;restore upper
- move.l map_flags(a1),d1
- move.l d0,d6
- move.l map_higher(a1),map_higher(a4) ;carry over the lower boundary
- or.l d1,map_flags(a4) ;carry over flags
- Remove ;remove this node
- move.l d6,a1
- bsr FreeContextMem ;release it again
- .nextchk:
- cmp.l d4,d3
- blo.s .okdone
- .next:
- move.l (a4),a4 ;get next mapping segment
- loop
-
- .okdone:
- moveq #1,d0
- .fail:
- move.l a2,a0
- bsr UnlockContext
- tst.l d0
- loadregs
- rts
- ;ENDFOLD
- ;FOLD BuildDefaultTable
- ;*************************************************
- ;** BuildDefaultTable **
- ;** **
- ;** if no default table is present, build one **
- ;** by scanning the ROM,RAM and the extensions **
- ;** Context *a0 **
- ;*************************************************
- xdef BuildDefaultTable
- BuildDefaultTable:
- saveregs a2/a4-a5
- move.l a0,a2 ;keep context
- move.l a7,a4 ;keep stack
-
- move.l #$f00000,a0
- move.l #$f80000,a1 ;diagnostic ROM
- move.l #(1<<mapp_rom),d0 ;status
- bsr _AddMap
- beq .fail
-
- move.l #$01000000,a1
- move.l a1,a0
- sub.l -$14(a0),a0 ;lower
- move.l #(1<<mapp_rom),d0 ;status
- bsr _AddMap
- beq .fail
- ;I don't want to add the 0xf0000000
- ;memory area. Undocumented
- move.l a6,a5
- move.l mulib_SysBase(a6),a6
- jsr Forbid(a6)
-
- moveq #0,d0
- move.l MemList(a6),a0 ;get list of all memheaders
- do
- tst.l (a0)
- break.s eq
- move.w mh_Attributes(a0),d0 ;get the attributes of this list
- move.l d0,-(a7) ;save to stack
- move.l mh_Upper(a0),-(a7)
- move.l mh_Lower(a0),-(a7) ;save lower
- move.l (a0),a0 ;get next
- loop.s
-
- jsr Permit(a6) ;done
- move.l a5,a6 ;restore mubase
-
- moveq #1,d0
- do
- cmp.l a4,a7
- break.s hs ;if all done, return
-
- move.l #(1<<mapp_copyback),d0 ;enable copyback if FAST
- movem.l (a7)+,a0-a1 ;get upper, lower
- move.l (a7)+,d1 ;get attributes
- btst #1,d1 ;chip mem?
- beq.s .isfast
- move.l #(1<<mapp_cacheinhibit),d0 ;if so, cache inhibited, precise exception model
- .isfast:
- bsr _AddMap
- while.s ne
- ;here: failure, whatever
- move.l a4,a7 ;restore stack
- tst.l d0 ;failure ?
- beq .fail
-
- sub.l a4,a4 ;configdev
- do
- move.l mulib_ExpansionBase(a6),a6 ;Expansion list
- move.l a4,a0 ;start with this configdev
- moveq #-1,d0
- move.l d0,d1 ;any manufacturer
- jsr FindConfigDev(a6) ;find configdevs
- move.l d0,a4 ;a configdev present
- move.l a5,a6
- tst.l d0
- break.s eq ;if not, then exit
-
- btst #ERTB_MEMLIST,er_Type(a4) ;is this external memory?
- reloop.s ne ;if so, ignore it
- movem.l cd_BoardAddr(a4),a0-a1 ;get address of the board
- adda.l a0,a1 ;upper size
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap
- beq .fail
- loop.s
-
- move.l #$bc0000,a0 ;actually, $bf0000. Don't be picky
- move.l #$c00000,a1
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap ;add the CIAs
- beq .fail
-
- move.l #$d80000,a0 ;actually, $dc0000
- move.l #$e00000,a1 ;Clock,SCSI,Motherboard resources,Chip Registers
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap ;add the CIAs
- beq .fail
-
- sub.l a0,a0
- move.l #$1000,a1
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap ;this is CHIP, but definitely available even though not in the memory list
- beq .fail
-
- move.l mulib_SysBase(a6),a6
- lea CardName,a1
- jsr OpenResource(a6) ;card.resource available?
- move.l a5,a6
- tst.l d0
- beq.s .nocard
-
- move.l #$600000,a0 ;base of the card resource
- move.l #$a80000,a1 ;is this right? (Nope. THATs right!)
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap
- beq .fail
-
- ;move.l #$da0000,a0 ;Gayle registers for IDE and PCMCIA
- ;move.l #$db0000,a1
- ;move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- ;bsr _AddMap
- ;beq.s .fail ;already mapped out
-
-
- .nocard:
- move.l mulib_SysBase(a6),a6
- lea CDStrapName,a1
- jsr FindResident(a6) ;cd available?
- move.l a5,a6
- tst.l d0
- beq.s .nocd
-
- move.l #$e00000,a0 ;base of the cd ROM
- move.l #$e80000,a1 ;is this right?
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap
- beq.s .fail
-
- move.l #$b80000,a0 ;ditto
- move.l #$bc0000,a1
- move.l #(1<<mapp_cacheinhibit),d0 ;cache inhibited, precise exception model
- bsr _AddMap
- beq.s .fail
- .nocd:
- move.l mulib_SysBase(a6),a0
- move.l $a(a0),d0 ;get name
- clr.w d0
- moveq #$20,d1
- swap d0
- cmp.l d1,d0 ;is this name in 20K up ?
- bne.s .noexec
-
- move.l #$200000,a0
- move.l #$280000,a1 ;is this a mapped ROM image
- move.l #(1<<mapp_writeprotected),d0 ;status
- bsr _AddMap
- beq.s .fail
- .noexec:
-
- move.l #$ff000000,a0
- move.l #$ff010000,a1
- move.l #(1<<mapp_cacheinhibit),d0 ;add the Zorro-III Configuration Unit
- bsr _AddMap
- beq.s .fail
-
- moveq #1,d0
- .fail:
- loadregs
- rts
-
- _AddMap:
- reserve map_len
- move.l d0,map_properties(a7)
- move.l a0,d0 ;get lower
- and.l mulib_PageMask(a6),d0
- clr.l map_userptr(a7)
- move.l d0,map_lower(a7)
- move.l a1,d0
- subq.l #1,d0
- add.l mulib_PageSize(a6),d0
- clr.l map_flags(a7)
- and.l mulib_PageMask(a6),d0
- moveq #-1,d1
- subq.l #1,d0
- move.l d0,map_higher(a7)
- move.l d1,map_mask(a7) ;mask in all bits
- move.l a2,a0
- move.l a7,a1
- bsr DefineMapping
- restore
- rts
- ;ENDFOLD
- ;FOLD AddTransparentTranslation
- ;*************************************************
- ;** AddTransparentTranslation **
- ;** **
- ;** Modify the context *a0 according to the **
- ;** address and mask in a1 **
- ;** Enable the properties d0, mask in d1 **
- ;** Context in a0 **
- ;*************************************************
- xdef AddTransparentTranslation
- AddTransparentTranslation:
- saveregs d2-d6/a2
- defvar
- auto.b att_map,map_len
- endvar
-
- move.l a1,d2 ;this is the mask
- move.l d0,map_Properties(a7)
- move.l a1,d3
- move.l d1,map_Mask(a7)
- not.b d2
- lsr.l #8,d3 ;this is the address
- clr.l map_UserPtr(a7)
- moveq #0,d4
- move.l #$01000000,d6 ;increment
- move.l a0,a2 ;keep context
- moveq #0,d5
- do
- move.w d4,d0 ;get the address
- eor.b d3,d0 ;compare with the address
- and.b d2,d0 ;and mask
- bne.s .next ;does it match ?
- move.l d5,map_lower(a7)
- move.l a2,a0
- move.l d5,map_higher(a7)
- add.l d6,map_higher(a7)
- move.l a7,a1
- subq.l #1,map_higher(a7)
- bsr DefineMapping
- beq.s .exit
- .next:
- add.l d6,d5
- addq.b #1,d4
- while.s ne
-
- moveq #1,d0
- .exit:
- freevar
- loadregs
- rts
- ;ENDFOLD
-
- ;FOLD SetGlobal
- ;*************************************************
- ;** SetGlobal **
- ;** define the context *a0 and all pages in it **
- ;** as global **
- ;*************************************************
- xdef SetGlobal
- SetGlobal:
- bsr LockContext ;arbitrate access
-
- bsetm ctxf_global,ctx_Flags(a0) ;now the global
- move.l ctx_Mapping(a0),a1 ;for all map nodes in this context
- do
- tst.l (a1) ;end of list ?
- break.s eq
-
- bsetm mapp_global,map_Properties(a1) ;set the global mask
- bne.s .next
-
- bsetm mapf_dirty,map_Flags(a1) ;this map has to be rebuild
- bsetm ctxf_dirty,ctx_Flags(a0) ;and therefore the context
- .next:
- move.l (a1),a1 ;next please
- loop
-
- bsr UnlockContext ;release Context
- rts
- ;ENDFOLD
-
- section main_data,data
- ;FOLD Strings
- CardName: dc.b "card.resource",0
- CDStrapName: dc.b "cdstrap",0
- ;ENDFOLD
- ;
-